#if UNITY_EDITOR
using System.Collections.Generic;
using NuoYan.Extension;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

[CustomPropertyDrawer(typeof(BidirectionalDictionary<,>))]
public class BidirectionalDictionaryDrawer : PropertyDrawer
{
    private const float KeyValueRatio = 0.4f;
    private const float VerticalSpacing = 2f;
    private static readonly Dictionary<string, bool> FoldoutStates = new Dictionary<string, bool>();
    private ReorderableList _cachedList;

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);

        // 获取唯一标识符用于存储折叠状态
        var stateKey = $"{property.propertyPath}@{property.serializedObject.targetObject.GetInstanceID()}";

        // 初始化折叠状态
        if (!FoldoutStates.ContainsKey(stateKey))
        {
            FoldoutStates[stateKey] = true; // 默认展开
        }

        // 绘制折叠箭头
        var foldoutRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
        FoldoutStates[stateKey] = EditorGUI.Foldout(foldoutRect, FoldoutStates[stateKey], label, true);

        if (FoldoutStates[stateKey])
        {
            // 获取字典条目属性
            var entriesProp = property.FindPropertyRelative("_entries");
            var list = GetReorderableList(entriesProp);

            // 计算列表绘制区域
            var listRect = new Rect(
                position.x,
                position.y + EditorGUIUtility.singleLineHeight + VerticalSpacing,
                position.width,
                list.GetHeight()
            );

            // 绘制可拖拽列表
            list.DoList(listRect);

            // 绘制重复键/值警告
            DrawDuplicatesWarning(position, entriesProp, listRect);
        }

        EditorGUI.EndProperty();
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        var stateKey = $"{property.propertyPath}@{property.serializedObject.targetObject.GetInstanceID()}";
        if (!FoldoutStates.TryGetValue(stateKey, out var isExpanded) || !isExpanded)
        {
            return EditorGUIUtility.singleLineHeight;
        }

        var entriesProp = property.FindPropertyRelative("_entries");
        var list = GetReorderableList(entriesProp);
        float height = EditorGUIUtility.singleLineHeight + list.GetHeight() + VerticalSpacing;

        if (CheckDuplicates(entriesProp, out _))
        {
            height += EditorGUIUtility.singleLineHeight * 2 + VerticalSpacing;
        }

        return height;
    }

    #region ReorderableList 核心配置
    private ReorderableList GetReorderableList(SerializedProperty listProperty)
    {
        if (_cachedList == null || _cachedList.serializedProperty != listProperty)
        {
            _cachedList = new ReorderableList(listProperty.serializedObject, listProperty, true, true, true, true)
            {
                draggable = true,
                displayAdd = true,
                displayRemove = true,

                // 元素绘制方式
                drawElementCallback = (rect, index, active, focused) =>
                {
                    var element = listProperty.GetArrayElementAtIndex(index);

                    // 关键点1：保留默认的拖拽手柄区域
                    rect.x += 12; // 给拖拽手柄留出空间
                    rect.width -= 12;

                    // 分割键值区域
                    var keyRect = new Rect(rect.x, rect.y, rect.width * KeyValueRatio, EditorGUIUtility.singleLineHeight);
                    var valueRect = new Rect(
                        rect.x + rect.width * KeyValueRatio + 5,
                        rect.y,
                        rect.width * (1 - KeyValueRatio) - 5,
                        EditorGUIUtility.singleLineHeight
                    );

                    // 绘制键值字段
                    EditorGUI.PropertyField(keyRect, element.FindPropertyRelative("Key"), GUIContent.none);
                    EditorGUI.PropertyField(valueRect, element.FindPropertyRelative("Value"), GUIContent.none);
                },

                // 关键点2：使用默认背景绘制（包含拖拽手柄）
                drawElementBackgroundCallback = (rect, index, active, focused) =>
                {
                    ReorderableList.defaultBehaviours.DrawElementBackground(rect, index, active, focused, true);
                },

                elementHeight = EditorGUIUtility.singleLineHeight + 4,
                drawHeaderCallback = rect => EditorGUI.LabelField(rect, "Entries"),

                // 关键点3：确保数据即时保存
                onReorderCallback = list =>
                {
                    list.serializedProperty.serializedObject.ApplyModifiedProperties();
                    EditorUtility.SetDirty(list.serializedProperty.serializedObject.targetObject);
                }
            };
        }
        return _cachedList;
    }
    #endregion

    #region 重复键值检测逻辑
    private void DrawDuplicatesWarning(Rect position, SerializedProperty entriesProp, Rect listRect)
    {
        string message;
        if (CheckDuplicates(entriesProp, out message))
        {
            var warningRect = new Rect(
                position.x,
                listRect.yMax + VerticalSpacing,
                position.width,
                EditorGUIUtility.singleLineHeight * 2
            );

            EditorGUI.HelpBox(warningRect, message, MessageType.Error);
        }
    }

    private bool CheckDuplicates(SerializedProperty entriesProp, out string message)
    {
        message = "";
        var keys = new HashSet<object>();
        var values = new HashSet<object>();
        bool hasKeyDup = false;
        bool hasValueDup = false;

        for (int i = 0; i < entriesProp.arraySize; i++)
        {
            var entry = entriesProp.GetArrayElementAtIndex(i);
            var key = GetPropertyValue(entry.FindPropertyRelative("Key"));
            var value = GetPropertyValue(entry.FindPropertyRelative("Value"));

            if (!keys.Add(key)) hasKeyDup = true;
            if (!values.Add(value)) hasValueDup = true;
        }

        if (hasKeyDup && hasValueDup)
            message = "Duplicate Keys and Values Detected!";
        else if (hasKeyDup)
            message = "Duplicate Keys Detected!";
        else if (hasValueDup)
            message = "Duplicate Values Detected!";

        return hasKeyDup || hasValueDup;
    }

    private object GetPropertyValue(SerializedProperty prop)
    {
        switch (prop.propertyType)
        {
            case SerializedPropertyType.Integer:
                return prop.intValue;
            case SerializedPropertyType.Boolean:
                return prop.boolValue;
            case SerializedPropertyType.Float:
                return prop.floatValue;
            case SerializedPropertyType.String:
                return prop.stringValue;
            case SerializedPropertyType.ObjectReference:
                return prop.objectReferenceValue;
            case SerializedPropertyType.Enum:
                return prop.enumValueIndex;
            default:
                return default;
        }
    }
    #endregion
    #region 折叠状态管理
    [InitializeOnLoadMethod]
    private static void ClearFoldoutStates()
    {
        // 每次编译后清空折叠状态
        FoldoutStates.Clear();
    }
    #endregion
}

#endif